package com.ruoyi.web.controller.api;

import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.WxLoginUser;
import com.ruoyi.common.utils.ImageUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.WxTokenService;
import com.ruoyi.task.domain.TaskUser;
import com.ruoyi.task.domain.VO.LoginUserVO;
import com.ruoyi.task.domain.VO.LoginVO;
import com.ruoyi.task.service.ITaskConfigService;
import com.ruoyi.task.service.ITaskUserService;
import com.ruoyi.task.service.WxAuthenticationService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@Api(tags = "登录相关接口")
@RestController
@RequestMapping("/api/login")
@Slf4j
public class LoginController extends BaseController {

    @Autowired
    private WxAuthenticationService wxAuthenticationService;

    @Autowired
    private ITaskUserService iTaskUserService;


    @Autowired
    private WxTokenService wxTokenService;

    @Autowired
    private ImageUtils imageUtils;

    @Autowired
    private ITaskConfigService iTaskConfigService;

    @Value("${wx.appid}")
    private String appid;
    @Value("${wx.appsecret}")
    private String appsecret;

    @Value("${wx.phonenumber}")
    private String phonenumber;

    @ApiOperation("一键登录")
    @PostMapping("login")
    public AjaxResult login(@Validated @RequestBody LoginVO loginVO){
        JSONObject jsonObject =  wxAuthenticationService.getOpenId(loginVO.getCode());
        log.info("登录信息："+jsonObject);
        String openid = (String)jsonObject.get("openid");
        WxLoginUser wxLoginUser = new WxLoginUser();
        if (StringUtils.isEmpty(openid)){
            return AjaxResult.error("登录失败");
        }
        TaskUser taskUser = iTaskUserService.selectTaskUserByOpenId(openid);
        if (taskUser == null){
            taskUser = new TaskUser();
            taskUser.setOpenId(openid);
            taskUser.setReferenceId(loginVO.getReferenceId());
            iTaskUserService.insertTaskUser(taskUser);
        }else {
        /*    if (loginVO.getReferenceId() != null && taskUser.getReferenceId() == null){
               // log.info("用户已存在，更新用户信息");
                taskUser.setReferenceId(loginVO.getReferenceId());
                iTaskUserService.updateTaskUser(taskUser);
            }*/

           /* if (loginVO.getReferenceId() != null && taskUser.getReferenceId() == null){
                // 新增：校验推荐人不能是自己
                if (loginVO.getReferenceId().equals(taskUser.getId())) {
                    return AjaxResult.error("不能绑定自己为推荐人");
                }
                // 新增：校验推荐链是否形成闭环
                List<TaskUser> current = iTaskUserService.selectTaskUserByReferenceId(taskUser.getId());
                taskUser.setReferenceId(loginVO.getReferenceId());
                iTaskUserService.updateTaskUser(taskUser);
            }*/

            // 替换原有的循环检查逻辑
            /*if (loginVO.getReferenceId() != null && taskUser.getReferenceId() == null){
                // 检查推荐人不能是自己
                if (loginVO.getReferenceId().equals(taskUser.getId())) {
                   // return AjaxResult.error("不能绑定自己为推荐人");
                }else{
                    taskUser.setReferenceId(loginVO.getReferenceId());
                    iTaskUserService.updateTaskUser(taskUser);
                }

                // 检查是否会形成循环引用
                if (isCircularReference(taskUser.getId(), loginVO.getReferenceId())) {
                   // return AjaxResult.error("不能设置该推荐人，会形成循环推荐关系");
                }else{
                    taskUser.setReferenceId(loginVO.getReferenceId());
                    iTaskUserService.updateTaskUser(taskUser);
                }

            }*/

            if (loginVO.getReferenceId() != null && taskUser.getReferenceId() == null) {
                // 仅当同时满足以下条件时更新：
                // 1.推荐人不是自己
                // 2.推荐人存在
                // 3.不会形成循环引用
                if (!loginVO.getReferenceId().equals(taskUser.getId())
                        && iTaskUserService.selectTaskUserById(loginVO.getReferenceId()) != null
                        && !isCircularReference(taskUser.getId(), loginVO.getReferenceId())) {
                    taskUser.setReferenceId(loginVO.getReferenceId());
                    iTaskUserService.updateTaskUser(taskUser);
                }
            }
        }
        String token ="";
        Map<String,Object> map1 = new HashMap<>();
        wxLoginUser.setOpenId(openid);
        wxLoginUser.setUserId(taskUser.getId());
        token =  wxTokenService.createToken(wxLoginUser);
        map1.put("token",token);
        return success(map1);
    }



    @GetMapping("login1")
    public AjaxResult login1(){
        LoginVO loginVO = new LoginVO();
        loginVO.setReferenceId(11L);
        String openid ="oW3ay7d_WbGPdmSrewJZSooZSfPU";
        TaskUser taskUser = iTaskUserService.selectTaskUserByOpenId(openid);
        if (taskUser == null){
            taskUser = new TaskUser();
            taskUser.setOpenId(openid);
            taskUser.setReferenceId(loginVO.getReferenceId());
            iTaskUserService.insertTaskUser(taskUser);
        }else {
        /*    if (loginVO.getReferenceId() != null && taskUser.getReferenceId() == null){
               // log.info("用户已存在，更新用户信息");
                taskUser.setReferenceId(loginVO.getReferenceId());
                iTaskUserService.updateTaskUser(taskUser);
            }*/

           /* if (loginVO.getReferenceId() != null && taskUser.getReferenceId() == null){
                // 新增：校验推荐人不能是自己
                if (loginVO.getReferenceId().equals(taskUser.getId())) {
                    return AjaxResult.error("不能绑定自己为推荐人");
                }
                // 新增：校验推荐链是否形成闭环
                List<TaskUser> current = iTaskUserService.selectTaskUserByReferenceId(taskUser.getId());
                taskUser.setReferenceId(loginVO.getReferenceId());
                iTaskUserService.updateTaskUser(taskUser);
            }*/

            // 替换原有的循环检查逻辑
          /*  if (loginVO.getReferenceId() != null && taskUser.getReferenceId() == null){
                // 检查推荐人不能是自己
                // 检查是否会形成循环引用
                if (loginVO.getReferenceId().equals(taskUser.getId()) || isCircularReference(taskUser.getId(), loginVO.getReferenceId())) {
                    // return AjaxResult.error("不能设置该推荐人，会形成循环推荐关系");
                }else{
                    taskUser.setReferenceId(loginVO.getReferenceId());
                    iTaskUserService.updateTaskUser(taskUser);
                }



            }*/

            if (!loginVO.getReferenceId().equals(taskUser.getId())
                    && iTaskUserService.selectTaskUserById(loginVO.getReferenceId()) != null
                    && !isCircularReference(taskUser.getId(), loginVO.getReferenceId())) {

                taskUser.setReferenceId(loginVO.getReferenceId());
                iTaskUserService.updateTaskUser(taskUser);
            }
        }
        String token ="";
        Map<String,Object> map1 = new HashMap<>();
        map1.put("token",token);
        return success(map1);
    }

    /**
     * 检查是否会形成循环引用
     * @param currentUserId 当前用户ID
     * @param referenceId 要设置的推荐人ID
     * @return true-会形成循环，false-不会形成循环
     */
    private boolean isCircularReference(Long currentUserId, Long referenceId) {
        Set<Long> visited = new HashSet<>();
        Long checkId = referenceId;

        // 向上追溯推荐链
        while (checkId != null) {
            // 如果在推荐链中发现了当前用户，说明会形成循环
            if (checkId.equals(currentUserId)) {
                return true;
            }

            // 防止无限循环（数据异常情况）
            if (visited.contains(checkId)) {
                break;
            }
            visited.add(checkId);

            // 查找上级推荐人
            TaskUser referenceUser = iTaskUserService.selectTaskUserById(checkId);
            if (referenceUser == null) {
                break;
            }
            checkId = referenceUser.getReferenceId();
        }

        return false;
    }

    @ApiOperation("修改登录接口")
    @PostMapping("updateUser")
    public AjaxResult updateUser(HttpServletRequest request, @Validated @RequestBody LoginUserVO loginUserVO){
        WxLoginUser wxLoginUser = wxTokenService.getWxUser(request);
        TaskUser taskUser = new TaskUser();
        taskUser.setId(wxLoginUser.getUserId());
        taskUser.setNickName(loginUserVO.getNickName());
        taskUser.setPhone(loginUserVO.getPhone());
        taskUser.setProfileLmg(loginUserVO.getProfileLmg());
        taskUser.setWxAccount(loginUserVO.getWxAccount());
        taskUser.setPaymentCode(loginUserVO.getPaymentCode());
        return success(iTaskUserService.updateTaskUser(taskUser));
    }


    @ApiOperation("获取登录信息")
    @PostMapping("getLoginInfo")
    public AjaxResult getLoginInfo(HttpServletRequest request, @Validated @RequestBody LoginUserVO loginUserVO){
        WxLoginUser wxLoginUser = wxTokenService.getWxUser(request);
        return success(iTaskUserService.selectTaskUserById(wxLoginUser.getUserId()));
    }


    @ApiOperation("上传视频或者图片")
    @PostMapping("upload")
    public AjaxResult upload(HttpServletRequest request, @RequestParam(value = "file", required = false) MultipartFile file){
        // WxLoginUser wxLoginUser = wxTokenService.getWxUser(request);
        log.info("上传文件：{}",file);
        Map<String, String> url = new HashMap<>();
        if (file != null && !file.isEmpty()) {
            // 获取文件原始名称
            String originalFilename = file.getOriginalFilename();
            if (originalFilename != null) {
                // 获取文件后缀
                int lastIndex = originalFilename.lastIndexOf('.');
                if (lastIndex != -1) {
                    String extension = originalFilename.substring(lastIndex + 1).toLowerCase();
                    // 判断文件类型
                    if (isImage(extension)) {
                        url = imageUtils.uploadImageQiniu(file);
                    } else if (isVideo(extension)) {
                        url = imageUtils.uploadImageQiniuMP4(file);
                    }
                }
            }
        }
        return AjaxResult.success(url);
    }

    @ApiOperation("获取配置信息")
    @GetMapping("getConfig")
    public AjaxResult getConfig(HttpServletRequest request){
        return success(iTaskConfigService.selectTaskConfigById(1L));
    }

    @ApiOperation("获取手机号")
    @GetMapping("getPhoneNumber")
    public AjaxResult getPhoneNumber(HttpServletRequest request, String mobileCode){
        Map<String,Object> map = new HashMap<>();
        String phone = wxAuthenticationService.getWxUserPhone(mobileCode);
        map.put("phone",phone);
        return success(map);
    }


    public String getWxUserPhone(String mobileCode) {
        // 获取Access_Token
        String accessToken = getAccessToken();
        // 请求解析手机号
        StringBuilder getPhoneNumberUrl = new StringBuilder(phonenumber);
        getPhoneNumberUrl.append("?access_token=").append(accessToken);
        Map<String, String> phoneNumberParam = new HashMap<>();
        phoneNumberParam.put("code", mobileCode);
        RestTemplate rest = new RestTemplate();
        ResponseEntity<HashMap> hashMapResponseEntity = rest.postForEntity(getPhoneNumberUrl.toString(), phoneNumberParam, HashMap.class);
        log.info("=== 微信手机授权请求解析手机号返回：{} ",hashMapResponseEntity);
        if (hashMapResponseEntity.getStatusCodeValue() != 200 || Objects.isNull(hashMapResponseEntity.getBody()) || (Integer) hashMapResponseEntity.getBody().get("errcode")!=0) {
            throw new RuntimeException("解析手机接口调用异常~");
        }
        //  log.info("=== 微信手机授权请求解析手机号返回：{} ",hashMapResponseEntity.getBody());
        LinkedHashMap phoneInfo = (LinkedHashMap)hashMapResponseEntity.getBody().get("phone_info");
        String purePhoneNumber = (String)phoneInfo.get("purePhoneNumber");
        return purePhoneNumber;
    }

    public static final String WX_ACCESE_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token";

    private String getAccessToken() {
        // 查询redis 是否有存放access_token避免过多次请求
        // 请求ACCESS_TOKEN
        StringBuilder accessTokenUrl = new StringBuilder(WX_ACCESE_TOKEN_URL);
        accessTokenUrl.append("?grant_type=client_credential");
        accessTokenUrl.append("&appid=").append(this.appid);
        accessTokenUrl.append("&secret=").append(this.appsecret);
        RestTemplate rest = new RestTemplate();
        ResponseEntity<HashMap> accessTokenRes = rest.getForEntity(accessTokenUrl.toString(), HashMap.class);
        log.info("=== 微信手机授权请求AccessToken返回：{} ",accessTokenRes);
        if (accessTokenRes.getStatusCodeValue() != 200 || Objects.isNull(accessTokenRes.getBody()) || Objects.nonNull(accessTokenRes.getBody().get("errcode"))) {
            throw new RuntimeException("Token接口调用异常~");
        }
        //  log.info("=== 微信手机授权请求AccessToken返回：{} ",accessTokenRes.getBody());
        String accessToken = accessTokenRes.getBody().get("access_token").toString();
        // 存放redis 设置两个小时超时时间
        //redisUtil.set(REDIS_KEY_ACCESS_TOKEN,accessToken,2L, TimeUnit.HOURS);
        return accessToken;
    }

    /**
     * 判断文件后缀是否为图片格式
     * @param extension 文件后缀
     * @return 如果是图片格式返回 true，否则返回 false
     */
    private boolean isImage(String extension) {
        return "jpg".equals(extension) || "jpeg".equals(extension) || "png".equals(extension) || "gif".equals(extension);
    }

    /**
     * 判断文件后缀是否为视频格式
     * @param extension 文件后缀
     * @return 如果是视频格式返回 true，否则返回 false
     */
    private boolean isVideo(String extension) {
        return "mp4".equals(extension) || "avi".equals(extension) || "mov".equals(extension) || "mkv".equals(extension);
    }


}
